﻿
// 2020/1/16: 首个记录
// 2020/3/10: 增加红灯/绿灯闪烁状态
// 2020/5/15: 移除编译warning
// 2020/7/20: 更新样本标题
// 2020/11/2: 增加停车位是否被占用字段
// 2020/11/12: 支持Spadas7
// 2022/11/2: 支持Spadas8.4
// 2023/9/12: StopSign改为TrafficSign，并增加TrafficSignType
// 2023/10/11: 补充部分英文注释
// 2024/5/20: 新增TrafficLightData.stopPosX/Y
// 2024/7/3: 基于新样本框架。枚举改为使用enum class
// 2025/4/7: 实现插值和fromSample
// 2025/8/4: 不使用cat宏

#ifndef TRAFFIC_SAMPLE_V2_H
#define TRAFFIC_SAMPLE_V2_H

#include "spadas.h"

namespace traffic_sample_v2
{
	using namespace spadas;

	// Elements
	enum class TrafficElementType
	{
		Invalid = 0,
		SpeedLimit = 1, // 限速标志
		TrafficSign = 2, // 交通标志
		TrafficLight = 3, // 交通信号灯
		StopLine = 4, // 停止线
		SpeedBump = 5, // 减速带
		ArrowMark = 6, // 路面箭头
		ProhibitionZone = 7, // 禁停区
		ParkingSlot = 8, // 停车位
		ZebraCrossing = 9, // 斑马线
	};

	enum class TrafficSignType
	{
		Stop = 0, // 停止标志

		NoEntry = 1, // 禁止驶入
		NoDriving = 2, // 禁止通行
		NoParking = 3, // 禁止停车
		NoLongTimeParking = 4, // 禁止长时间停车
		NoVehicle = 5, // 禁止机动车驶入
		NoTruck = 6, // 禁止货车驶入
		NoBus = 7, // 禁止客车驶入
		NoPedestrian = 8, // 禁止行人进入
		NoLeftTurn = 9, // 禁止左转
		NoRightTurn = 10, // 禁止右转
		NoAnyTurn = 11, // 禁止转弯
		NoForward = 12, // 禁止直行
		NoForwardOrLeft = 13, // 禁止直行或左转
		NoForwardOrRight = 14, // 禁止直行或右转
		NoUTurn = 15, // 禁止调头
		NoHorn = 16, // 禁止鸣笛
		NoOvertake = 17, // 禁止超车
		NoOvertakeEnder = 18, // 禁止超车区间结束
		NoDangerousGoods = 19, // 禁止危险品车辆驶入

		LowSpeedLimit = 50, // 低速限速
		SpeedLimitEnder = 51, // 限速区间结束
		WeightLimitWheel = 52, // 轴重限重
		WeightLimitTotal = 53, // 全车限重
		HeightLimit = 54, // 高度限制
		WidthLimit = 55, // 宽度限制
		Yield = 56, // 让行标志
		StopAndCheck = 57, // 停车检查

		GeneralSign = 100, // 指示类标志
		GeneralNoSpecialVehicle = 101, // 禁止特种车辆驶入
		GeneralConstruction = 102, // 施工标志
		GeneralWarning = 103, // 警告牌
		GeneralGreenBackground = 104, // 绿底指示牌
		GeneralBlueBackground = 105, // 蓝底指示牌
		GeneralRedBackground = 106, // 红底指示牌
		GeneralWhiteBackground = 107, // 白底指示牌
		GeneralYellowRoadID = 108, // 黄底道路ID牌
		GeneralRedRoadID = 109, // 红底道路ID牌
	};

	struct OptBool
	{
		Bool valid;
		Bool value;
	};

	struct OptDouble
	{
		Bool valid;
		Double value;
	};

	struct ArrowCombination
	{
		Bool valid; // FALSE while direction is not specified / 是否有效，若不分方向(如实心圆交通灯信号)则为FALSE
		Bool goStraight; // 直行
		Bool turnLeft; // 左转
		Bool turnRight; // 右转
		Bool uTurn; // 调头
	};

	struct SpeedLimitData
	{
		UInt limitedSpeed; // [KPH] 限速
		OptDouble posX; // [m] 纵向位置
		OptDouble posY; // [m] 横向位置
		OptDouble posZ; // [m] 垂直位置
	};

	struct TrafficSignData
	{
		TrafficSignType signType; // 交通标志类别
		OptDouble posX; // [m] 纵向位置
		OptDouble posY; // [m] 横向位置
		OptDouble posZ; // [m] 垂直位置
	};

	enum class TrafficLightState
	{
		Invalid = 0,
		Stop = 1, // 红灯
		Continue = 2, // 黄灯
		Caution = 3, // 黄灯闪烁
		Allow = 4, // 绿灯
		AllowFlash = 5, // 绿灯闪烁
		StopFlash = 6, // 红灯闪烁
	};

	struct TrafficLightData
	{
		TrafficLightState state; // 信号灯状态
		ArrowCombination arrows; // 信号灯的箭头组合
		OptDouble posX; // [m] 纵向位置
		OptDouble posY; // [m] 横向位置
		OptDouble posZ; // [m] 垂直位置
		OptDouble stopPosX; // [m] 纵向停止位置
		OptDouble stopPosY; // [m] 横向停止位置
	};

	struct StopLineData
	{
		Double distance; // [m] 停止线与x轴相交位置
		OptDouble heading; // [°] 停止线法线朝向，逆时针为正方向
	};

	struct SpeedBumpData
	{
		Double distance; // [m] 减速带与x轴相交位置
		OptDouble heading; // [°] 减速带法线朝向，逆时针为正方向
	};

	struct ArrowMarkData
	{
		ArrowCombination arrows; // 路面标志的箭头组合
		OptDouble posX; // [m] 纵向位置
		OptDouble posY; // [m] 横向位置
	};

	struct ProhibitionZoneData
	{
		Double centerX; // [m] 禁停区中央的纵向位置
		Double centerY; // [m] 禁停区中央的横向位置
		Double width; // [m] 禁停区的宽度
		Double length; // [m] 禁停区的长度
		OptDouble heading; // [°] 禁停区的朝向(沿长度方向)，逆时针为正方向
	};

	enum class ParkingSlotOccupancy
	{
		Unknown = 0, // 未知
		NotOccupied = 1, // 未被占用
		Occupied = 2, // 被占用
	};

	struct ParkingSlotData
	{
		Double centerX; // [m] 停车位中央的纵向位置
		Double centerY; // [m] 停车位中央的横向位置
		Double width; // [m] 停车位的宽度
		Double length; // [m] 停车位的长度
		OptDouble heading; // [°] 停车位的朝向(沿长度方向)，逆时针为正方向
		ParkingSlotOccupancy occupancy; // 停车位是否被占用
	};

	struct ZebraCrossingData
	{
		Double nearDistance; // [m] 斑马线近端与x轴相交位置
		OptDouble farDistance; // [m] 斑马线远端与x轴相交位置
		OptDouble heading; // [°] 斑马线的朝向，逆时针为正方向
	};

	// Sample
	union TrafficElementData
	{
		SpeedLimitData speedLimit;
		TrafficSignData trafficSign;
		TrafficLightData trafficLight;
		StopLineData stopLine;
		SpeedBumpData speedBump;
		ArrowMarkData arrowMark;
		ProhibitionZoneData prohibitionZone;
		ParkingSlotData parkingSlot;
		ZebraCrossingData zebraCrossing;
	};

	struct TrafficElement
	{
		TrafficElementType type; // 交通元素类别
		Int id; // 0 as invalid / 交通元素ID，0表示无效
		OptionalInt rawID; // 交通元素的原始ID
		TrafficElementData data; // 交通元素数据
	};

	struct TrafficSampleData
	{
		Array<TrafficElement> elements; // List of traffic elements / 交通元素列表

		TrafficSampleData()
		{}
	};

	class TrafficSample : public Object<class TrafficSampleVars>
	{
	public:
		SPADAS_TYPE("traffic_sample_v2.TrafficSample")

		TrafficSample();
		FullTimestamp& timestamp();
		TrafficSampleData *operator ->();

		static String getProtocolName(UInt channel);
		SessionGeneralSample toGeneralSample();

		static Array<String> getProtocolNames(UInt channel);
		Bool fromGeneralSample(String protocol, SessionGeneralSample generalSample);
	};
}

#endif
